﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Dts.Runtime; // Requires reference to Microsoft.SQLServer.ManagedDTS

namespace ToddMcDermid.SSIS
{
    // This attribute tells SSIS about your Task.
    [DtsTask(
        DisplayName = "File Properties Task",
        TaskType = "General",
        TaskContact = "Todd McDermid",
        UITypeName = "ToddMcDermid.SSIS.FilePropertiesTaskInterface,FilePropertiesTask100,Version=1.0.0.0,Culture = Neutral,PublicKeyToken = 6c005605b216cf47",
        IconResource = "ToddMcDermid.SSIS.FilePropertiesTask.ico",
        RequiredProductLevel = DTSProductLevel.None)]
    public class FilePropertiesTask : Task
    {
        #region Public Constants
        public const string VARIABLE_ALWAYSTRUE = "<static true value>";
        public const string VARIABLE_ALWAYSFALSE = "<static false value>";
        #endregion

        #region Public Enumerations
        public enum PropertySourceType
        {
            Static_Value,
            Variable
        }

        public enum FileMissingActionType
        {
            Task_Always_Succeeds_and_Records_File_Existence_In_Variable,
            Task_Fails_if_the_File_Does_Not_Exist
        }

        public enum PropertyActionType
        {
            Ignore,
            Read,
            Write,
            Write_Then_Read
        }
        #endregion

        #region Private Variables
        private PropertySourceType _filePathNameType;
        private string _filePathName;
        private FileMissingActionType _fileMissingAction;
        private string __varNameFileExistence;
        private string _varNameFileLength;
        private string _varNameParsedFileDirectory;
        private string _varNameParsedFileName;
        private string _varNameConstructedFullFilePath;
        private string _varNameFileReadable;
        private string _varNameFileWriteable;
        private int _fileWaitSeconds;
        private PropertyActionType _propertyActionCreationDate;
        private string _varNameCreationDate;
        private PropertyActionType _propertyActionAccessDate;
        private string _varNameAccessDate;
        private PropertyActionType _propertyActionModifiedDate;
        private string _varNameModifiedDate;
        private PropertyActionType _propertyActionAttributeArchive;
        private string _varNameAttributeArchive;
        private PropertyActionType _propertyActionAttributeCompressed;
        private string _varNameAttributeCompressed;
        private PropertyActionType _propertyActionAttributeEncrypted;
        private string _varNameAttributeEncrypted;
        private PropertyActionType _propertyActionAttributeHidden;
        private string _varNameAttributeHidden;
        private PropertyActionType _propertyActionAttributeReadOnly;
        private string _varNameAttributeReadOnly;
        private PropertyActionType _propertyActionAttributeSystem;
        private string _varNameAttributeSystem;
        private PropertyActionType _propertyActionAttributeTemporary;
        private string _varNameAttributeTemporary;
        #endregion

        #region Constructor
        public FilePropertiesTask()
        {
            this._filePathNameType = PropertySourceType.Variable;
            this._filePathName = null;
            this._fileMissingAction = FileMissingActionType.Task_Fails_if_the_File_Does_Not_Exist;
            this._varNameFileExistence = null;
            this._varNameFileLength = null;
            this._varNameParsedFileDirectory = null;
            this._varNameParsedFileName = null;
            this._varNameConstructedFullFilePath = null;
            this._varNameFileReadable = null;
            this._varNameFileWriteable = null;
            this._propertyActionCreationDate = PropertyActionType.Ignore;
            this._varNameCreationDate = null;
            this._propertyActionAccessDate = PropertyActionType.Ignore;
            this._varNameAccessDate = null;
            this._propertyActionModifiedDate = PropertyActionType.Ignore;
            this._varNameModifiedDate = null;
            this._propertyActionAttributeArchive = PropertyActionType.Ignore;
            this._varNameAttributeArchive = null;
            this._propertyActionAttributeCompressed = PropertyActionType.Ignore;
            this._varNameAttributeCompressed = null;
            this._propertyActionAttributeEncrypted = PropertyActionType.Ignore;
            this._varNameAttributeEncrypted = null;
            this._propertyActionAttributeHidden = PropertyActionType.Ignore;
            this._varNameAttributeHidden = null;
            this._propertyActionAttributeReadOnly = PropertyActionType.Ignore;
            this._varNameAttributeReadOnly = null;
            this._propertyActionAttributeSystem = PropertyActionType.Ignore;
            this._varNameAttributeSystem = null;
            this._propertyActionAttributeTemporary = PropertyActionType.Ignore;
            this._varNameAttributeTemporary = null;
        }
        #endregion

        #region Public Properties
        #region File Name
        public PropertySourceType FilePathNameSource
        {
            get { return this._filePathNameType; }
            set { this._filePathNameType = value; }
        }

        public string FilePathName
        {
            get { return this._filePathName; }
            set 
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._filePathName = null;
                }
                else
                {
                    this._filePathName = value;
                }
            }
        }
        #endregion

        #region Existence
        public FileMissingActionType FileMissingAction
        {
            get { return this._fileMissingAction; }
            set { this._fileMissingAction = value; }
        }

        public int FileWaitSeconds
        {
            get { return this._fileWaitSeconds; }
            set { this._fileWaitSeconds = value; }
        }

        public string FileExistenceVariableName
        {
            get { return this._varNameFileExistence; }
            set { this._varNameFileExistence = value; }
        }

        private string _varNameFileExistence
        {
            get 
            {
                if ((this._fileMissingAction == FileMissingActionType.Task_Fails_if_the_File_Does_Not_Exist) || (this.__varNameFileExistence.Trim() == ""))
                {
                    return null;
                }
                else
                {
                    return this.__varNameFileExistence;
                }
            }
            set
            {
                this.__varNameFileExistence = value;
            }
        }
        #endregion

        #region File Name (De)Construction
        public string ParsedFileDirectoryVariableName
        {
            get { return this._varNameParsedFileDirectory; }
            set
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._varNameParsedFileDirectory = null;
                }
                else
                {
                    this._varNameParsedFileDirectory = value;
                }
            }
        }

        public string ParsedFileNameVariableName
        {
            get { return this._varNameParsedFileName; }
            set
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._varNameParsedFileName = null;
                }
                else
                {
                    this._varNameParsedFileName = value;
                }
            }
        }

        public string ConstructedFullFilePathVariableName
        {
            get { return this._varNameConstructedFullFilePath; }
            set
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._varNameConstructedFullFilePath = null;
                }
                else
                {
                    this._varNameConstructedFullFilePath = value;
                }
            }
        }
        #endregion

        #region Readable/writable
        public string FileReadableVariableName
        {
            get { return this._varNameFileReadable; }
            set
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._varNameFileReadable = null;
                }
                else
                {
                    this._varNameFileReadable = value;
                }
            }
        }

        public string FileWriteableVariableName
        {
            get { return this._varNameFileWriteable; }
            set
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._varNameFileWriteable = null;
                }
                else
                {
                    this._varNameFileWriteable = value;
                }
            }
        }
        #endregion

        #region File Length
        public string FileLengthVariableName
        {
            get { return this._varNameFileLength; }
            set
            {
                if ((value == null) || (value.Trim() == ""))
                {
                    this._varNameFileLength = null;
                }
                else
                {
                    this._varNameFileLength = value;
                }
            }
        }
        #endregion

        #region Date Properties
        public PropertyActionType CreationDateAction
        {
            get { return this._propertyActionCreationDate; }
            set { this._propertyActionCreationDate = value; }
        }

        public string CreationDateVariableName
        {
            get { return this._varNameCreationDate; }
            set
            {
                if ((this._propertyActionCreationDate == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameCreationDate = null;
                    this._propertyActionCreationDate = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameCreationDate = value;
                }
            }
        }

        public PropertyActionType AccessDateAction
        {
            get { return this._propertyActionAccessDate; }
            set { this._propertyActionAccessDate = value; }
        }

        public string AccessDateVariableName
        {
            get { return this._varNameAccessDate; }
            set
            {
                if ((this._propertyActionAccessDate == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAccessDate = null;
                    this._propertyActionAccessDate = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAccessDate = value;
                }
            }
        }

        public PropertyActionType ModifiedDateAction
        {
            get { return this._propertyActionModifiedDate; }
            set { this._propertyActionModifiedDate = value; }
        }

        public string ModifiedDateVariableName
        {
            get { return this._varNameModifiedDate; }
            set
            {
                if ((this._propertyActionModifiedDate == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameModifiedDate = null;
                    this._propertyActionModifiedDate = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameModifiedDate = value;
                }
            }
        }
        #endregion

        #region Attribute Properties
        public PropertyActionType AttributeArchiveAction
        {
            get { return this._propertyActionAttributeArchive; }
            set { this._propertyActionAttributeArchive = value; }
        }

        public string AttributeArchiveVariableName
        {
            get { return this._varNameAttributeArchive; }
            set
            {
                if ((this._propertyActionAttributeArchive == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeArchive = null;
                    this._propertyActionAttributeArchive = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeArchive = value;
                }
            }
        }

        public PropertyActionType AttributeCompressedAction
        {
            get { return this._propertyActionAttributeCompressed; }
            set { this._propertyActionAttributeCompressed = value; }
        }

        public string AttributeCompressedVariableName
        {
            get { return this._varNameAttributeCompressed; }
            set
            {
                if ((this._propertyActionAttributeCompressed == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeCompressed = null;
                    this._propertyActionAttributeCompressed = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeCompressed = value;
                }
            }
        }

        public PropertyActionType AttributeEncryptedAction
        {
            get { return this._propertyActionAttributeEncrypted; }
            set { this._propertyActionAttributeEncrypted = value; }
        }

        public string AttributeEncryptedVariableName
        {
            get { return this._varNameAttributeEncrypted; }
            set
            {
                if ((this._propertyActionAttributeEncrypted == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeEncrypted = null;
                    this._propertyActionAttributeEncrypted = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeEncrypted = value;
                }
            }
        }

        public PropertyActionType AttributeHiddenAction
        {
            get { return this._propertyActionAttributeHidden; }
            set { this._propertyActionAttributeHidden = value; }
        }

        public string AttributeHiddenVariableName
        {
            get { return this._varNameAttributeHidden; }
            set
            {
                if ((this._propertyActionAttributeHidden == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeHidden = null;
                    this._propertyActionAttributeHidden = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeHidden = value;
                }
            }
        }

        public PropertyActionType AttributeReadOnlyAction
        {
            get { return this._propertyActionAttributeReadOnly; }
            set { this._propertyActionAttributeReadOnly = value; }
        }

        public string AttributeReadOnlyVariableName
        {
            get { return this._varNameAttributeReadOnly; }
            set
            {
                if ((this._propertyActionAttributeReadOnly == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeReadOnly = null;
                    this._propertyActionAttributeReadOnly = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeReadOnly = value;
                }
            }
        }

        public PropertyActionType AttributeSystemAction
        {
            get { return this._propertyActionAttributeSystem; }
            set { this._propertyActionAttributeSystem = value; }
        }

        public string AttributeSystemVariableName
        {
            get { return this._varNameAttributeSystem; }
            set
            {
                if ((this._propertyActionAttributeSystem == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeSystem = null;
                    this._propertyActionAttributeSystem = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeSystem = value;
                }
            }
        }

        public PropertyActionType AttributeTemporaryAction
        {
            get { return this._propertyActionAttributeTemporary; }
            set { this._propertyActionAttributeTemporary = value; }
        }

        public string AttributeTemporaryVariableName
        {
            get { return this._varNameAttributeTemporary; }
            set
            {
                if ((this._propertyActionAttributeTemporary == PropertyActionType.Ignore) || (value == null) || (value.Trim() == ""))
                {
                    this._varNameAttributeTemporary = null;
                    this._propertyActionAttributeTemporary = PropertyActionType.Ignore;
                }
                else
                {
                    this._varNameAttributeTemporary = value;
                }
            }
        }
        #endregion
        #endregion

        #region Private Methods (helpers)
        public string GetResolvedFilePathName(VariableDispenser variableDispenser)
        {
            string resolvedFilePathName = null;

            if (this._filePathNameType == PropertySourceType.Static_Value)
            {
                resolvedFilePathName = this._filePathName;
            }
            else
            {
                variableDispenser.LockForRead(this._filePathName);
                Variables vars = null;
                variableDispenser.GetVariables(ref vars);
                resolvedFilePathName = (string)vars[0].Value;
                vars.Unlock();
            }

            return resolvedFilePathName;
        }
        #endregion

        #region Task Implementation
        #region InitializeTask
        /// <summary>
        /// This method is called when the Task is initially placed on the design surface,
        /// before Validate is called, before Execute is called, and before any properties
        /// are read or written to (by the SSIS engine).
        /// </summary>
        public override void InitializeTask(Connections connections, VariableDispenser variableDispenser,
            IDTSInfoEvents events, IDTSLogging log, EventInfos eventInfos,
            LogEntryInfos logEntryInfos, ObjectReferenceTracker refTracker)
        {
            base.InitializeTask(connections, variableDispenser, events, log, eventInfos, logEntryInfos, refTracker);
        }
        #endregion

        public class TaskXML
        {
            public struct PropertyStruct
            {
                public string DataType;
                public string Value;
            }

            private SortedList<string, PropertyStruct> _properties;

            public TaskXML(string originalXML)
            {
                this._properties = new SortedList<string, PropertyStruct>();

                string propertyStrings = originalXML.Replace("<InnerObject>", "").Replace("</InnerObject>", "");
                while (propertyStrings.Length > 0)
                {
                    int endOfProperty = propertyStrings.IndexOf("/>") + 2;
                    string propertyString = propertyStrings.Substring(0, endOfProperty);
                    propertyStrings = propertyStrings.Substring(endOfProperty);

                    string propertyName = propertyString.Substring(1, propertyString.IndexOf(" ") - 1);
                    string propertyType = propertyString.Substring(propertyString.IndexOf("Type=\"") + 6, 1);
                    int valueStart = propertyString.IndexOf("Value=\"") + 7;
                    int valueEnd = propertyString.IndexOf("\"/>");
                    string propertyValue = propertyString.Substring(valueStart, valueEnd - valueStart);

                    PropertyStruct propertyStruct = new PropertyStruct();
                    propertyStruct.Value = propertyValue;
                    propertyStruct.DataType = propertyType;
                    this._properties.Add(propertyName, propertyStruct);
                }
            }

            public bool HasProperty(string propertyName)
            {
                return (this._properties.ContainsKey(propertyName));
            }

            public void AddProperty(string propertyName, string dataType, string value)
            {
                PropertyStruct property = new PropertyStruct();
                property.DataType = dataType;
                property.Value = value;

                this._properties.Add(propertyName, property);
            }

            public string ToXML()
            {
                StringBuilder newXML = new StringBuilder();
                newXML.Append("<InnerObject>");
                foreach (KeyValuePair<string, PropertyStruct> property in this._properties)
                {
                    newXML.Append("<");
                    newXML.Append(property.Key);
                    newXML.Append(" Type=\"");
                    newXML.Append(((PropertyStruct)property.Value).DataType);
                    newXML.Append("\" Value=\"");
                    newXML.Append(((PropertyStruct)property.Value).Value);
                    newXML.Append("\"/>");
                }
                newXML.Append("</InnerObject>");

                return newXML.ToString();
            }
        }

        public override int Version
        {
            get
            {
                return 1;
            }
        }

        #region Validate
        /// <summary>
        /// This method is called frequently at design time and runtime.  It's purpose is
        /// to tell SSIS if "everything is OK".  You should check that any SSIS variables
        /// you will use at runtime actually exist in the VariableDispenser, that they're 
        /// the right type, and contain valid values.  You should check that any connections
        /// you intend to use exist in the Connections collection, and that you can connect
        /// to them.
        /// </summary>
        public override DTSExecResult Validate(Connections connections, VariableDispenser variableDispenser, IDTSComponentEvents componentEvents, IDTSLogging log)
        {
            DTSExecResult result = base.Validate(connections, variableDispenser, componentEvents, log);

            if (result == DTSExecResult.Success)
            {
                #region Check that filename SSIS variable exists (don't bother to check contents)
                try
                {
                    if (this._filePathNameType == PropertySourceType.Variable)
                    {
                        if (this._filePathName == null)
                        {
                            componentEvents.FireError(0, "", "No variable is specified for the file name.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else if (!variableDispenser.Contains(this._filePathName))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._filePathName + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._filePathName);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.String)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._filePathName + "' is not a String type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                    else
                    {
                        if (this._filePathName == null)
                        {
                            componentEvents.FireError(0, "", "No file name is specified.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the file name property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check file existence action properties are set properly
                try
                {
                    if (this._fileMissingAction == FileMissingActionType.Task_Always_Succeeds_and_Records_File_Existence_In_Variable)
                    {
                        if (this._varNameFileExistence == null)
                        {
                            componentEvents.FireError(0, "", "No variable is specified to contain results of file existence.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else if (!variableDispenser.Contains(this._varNameFileExistence))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameFileExistence + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameFileExistence);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.Boolean)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileExistence + "' is not a Boolean type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the file existence variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check parsed file directory property is set properly
                try
                {
                    if (this._varNameParsedFileDirectory != null)
                    {
                        if (!variableDispenser.Contains(this._varNameParsedFileDirectory))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameParsedFileDirectory + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameParsedFileDirectory);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.String)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameParsedFileDirectory + "' is not a String type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameParsedFileDirectory + "' can't be written to.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the parsed file name variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check parsed file name property is set properly
                try
                {
                    if (this._varNameParsedFileName != null)
                    {
                        if (!variableDispenser.Contains(this._varNameParsedFileName))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameParsedFileName + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameParsedFileName);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.String)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameParsedFileName + "' is not a String type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameParsedFileName + "' can't be written to.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the parsed file name variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check constructed full file path property is set properly
                try
                {
                    if (this._varNameConstructedFullFilePath != null)
                    {
                        if (!variableDispenser.Contains(this._varNameConstructedFullFilePath))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameConstructedFullFilePath + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameConstructedFullFilePath);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.String)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameConstructedFullFilePath + "' is not a String type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameConstructedFullFilePath + "' can't be written to.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the constructed full file path variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check file readable property is set properly
                try
                {
                    if (this._varNameFileReadable != null)
                    {
                        if (!variableDispenser.Contains(this._varNameFileReadable))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameFileReadable + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameFileReadable);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.Boolean)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileReadable + "' is not a Boolean type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileReadable + "' can't be written to.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the file access variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check file writeable property is set properly
                try
                {
                    if (this._varNameFileWriteable != null)
                    {
                        if (!variableDispenser.Contains(this._varNameFileWriteable))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameFileWriteable + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameFileWriteable);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if (vars[0].DataType != TypeCode.Boolean)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileWriteable + "' is not a Boolean type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileWriteable + "' can't be written to.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the file access variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check file length property is set properly
                try
                {
                    if (this._varNameFileLength != null)
                    {
                        if (!variableDispenser.Contains(this._varNameFileLength))
                        {
                            componentEvents.FireError(0, "", "The variable '" + this._varNameFileLength + "' does not exist.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameFileLength);
                            Variables vars = null;
                            variableDispenser.GetVariables(ref vars);
                            if ((vars[0].DataType != TypeCode.Int64) && (vars[0].DataType != TypeCode.UInt64))
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileLength + "' is not an Int64 or UInt64 type.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + this._varNameFileLength + "' can't be written to.", "", 0);
                                result = DTSExecResult.Failure;
                            }
                            vars.Unlock();
                        }
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "", "An error occurred validating the file length variable property: " + ex.Message + ".", "", 0);
                    result = DTSExecResult.Failure;
                }
                #endregion
                #endregion

                #region Check Creation Date Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Creation Date",
                    this._propertyActionCreationDate, this._varNameCreationDate, new TypeCode[] { TypeCode.DateTime }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Access Date Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Access Date",
                    this._propertyActionAccessDate, this._varNameAccessDate, new TypeCode[] { TypeCode.DateTime }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Modified Date Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Modified Date",
                    this._propertyActionModifiedDate, this._varNameModifiedDate, new TypeCode[] { TypeCode.DateTime }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Archive Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Archive Attribute",
                    this._propertyActionAttributeArchive, this._varNameAttributeArchive, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Compressed Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Compressed Attribute",
                    this._propertyActionAttributeCompressed, this._varNameAttributeCompressed, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Encrypted Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Encrypted Attribute",
                    this._propertyActionAttributeEncrypted, this._varNameAttributeEncrypted, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Hidden Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Hidden Attribute",
                    this._propertyActionAttributeHidden, this._varNameAttributeHidden, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check ReadOnly Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "ReadOnly Attribute",
                    this._propertyActionAttributeReadOnly, this._varNameAttributeReadOnly, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check System Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "System Attribute",
                    this._propertyActionAttributeSystem, this._varNameAttributeSystem, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check Temporary Attribute Property Validity
                if (!this.ValidateIndividualProperty(variableDispenser, componentEvents, "Temporary Attribute",
                    this._propertyActionAttributeTemporary, this._varNameAttributeTemporary, new TypeCode[] { TypeCode.Boolean }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check combination of date properties
                if (!this.ValidateCombinedProperties(componentEvents, 
                    new string[] { this._varNameAccessDate, this._varNameCreationDate, this._varNameModifiedDate }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion

                #region Check combination of string properties
                if (!this.ValidateCombinedProperties(componentEvents,
                    new string[] { this._varNameAccessDate, this._varNameAttributeArchive, this._varNameAttributeCompressed, this._varNameAttributeEncrypted,
                    this._varNameAttributeHidden, this._varNameAttributeReadOnly, this._varNameAttributeSystem, this._varNameAttributeTemporary,
                    this._varNameConstructedFullFilePath, this._varNameCreationDate, this._varNameFileExistence, this._varNameFileLength, this._varNameFileReadable,
                    this._varNameFileWriteable, this._varNameModifiedDate, this._varNameParsedFileDirectory, this._varNameParsedFileName }))
                {
                    result = DTSExecResult.Failure;
                }
                #endregion
            }

            return result;
        }

        #region ValidateIndividualProperty
        private bool ValidateIndividualProperty(VariableDispenser variableDispenser, IDTSComponentEvents componentEvents,
            string propertyName, PropertyActionType propertyActionType, string variableName, TypeCode[] allowableTypes)
        {
            bool result = true;
            try
            {
                if ((variableName != null) && (propertyActionType != PropertyActionType.Ignore))
                {
                    if ((variableName == VARIABLE_ALWAYSTRUE) || (variableName == VARIABLE_ALWAYSFALSE))
                    {
                        if (propertyActionType != PropertyActionType.Write)
                        {
                            componentEvents.FireError(0, "", "Can't used (reserved) static true/false directives when value is configured to be read, not just written.", "", 0);
                            result = false;
                        }
                        else
                        {
                            result = true;
                        }
                    }
                    else if (!variableDispenser.Contains(variableName))
                    {
                        componentEvents.FireError(0, "", "The variable '" + variableName + "' does not exist.", "", 0);
                        result = false;
                    }
                    else
                    {
                        variableDispenser.LockForRead(variableName);
                        Variables vars = null;
                        variableDispenser.GetVariables(ref vars);
                        List<TypeCode> allowableTypeList = new List<TypeCode>(allowableTypes);
                        if (!allowableTypeList.Contains(vars[0].DataType))
                        {
                            StringBuilder allowableTypeNames = new StringBuilder();
                            foreach (TypeCode allowableType in allowableTypes)
                            {
                                allowableTypeNames.Append(allowableType.ToString() + ", ");
                            }
                            allowableTypeNames.Length -= 2;
                            componentEvents.FireError(0, "", "The variable '" + variableName + "' does not permit " + vars[0].DataType.ToString() + ", only " + allowableTypeNames.ToString() + ".", "", 0);
                            result = false;
                        }
                        else if ((propertyActionType == PropertyActionType.Read) || (propertyActionType == PropertyActionType.Write_Then_Read))
                        {
                            if (vars[0].SystemVariable)
                            {
                                componentEvents.FireError(0, "", "System variables (" + variableName + ") can't be written to.", "", 0);
                                result = false;
                            }
                            else if (vars[0].ReadOnly)
                            {
                                componentEvents.FireError(0, "", "The variable '" + variableName + "' must be marked ReadWrite.", "", 0);
                                result = false;
                            }
                        }
                        vars.Unlock();
                    }
                }
            }
            #region catch ...
            catch (Exception ex)
            {
                componentEvents.FireError(0, "", "An error occurred validating the " + propertyName + " variable property: " + ex.Message + ".", "", 0);
                result = false;
            }
            #endregion

            return result;
        }
        #endregion

        #region ValidateCombinedProperties
        private bool ValidateCombinedProperties(IDTSComponentEvents componentEvents, string[] variableNames)
        {
            bool result = true;

            try
            {
                List<string> variableNameList = new List<string>(variableNames);
                variableNameList.Sort();
                variableNameList.Remove(VARIABLE_ALWAYSTRUE);
                variableNameList.Remove(VARIABLE_ALWAYSFALSE);
                for (int index = 1; index < variableNameList.Count; index++)
                {
                    if ((variableNameList[index] != null) && (variableNameList[index] == variableNameList[index - 1]))
                    {
                        componentEvents.FireError(0, "", "Multiple properties can not refer to the same variable " + variableNameList[index] + ".", "", 0);
                        result = false;
                    }
                }
            }
            #region catch ...
            catch (Exception ex)
            {
                componentEvents.FireError(0, "", "An error occurred validating combined properties: " + ex.Message + ".", "", 0);
                result = false;
            }
            #endregion

            return result;
        }
        #endregion
        #endregion

        #region Execute
        /// <summary>
        /// This method is called only at runtime, and does all the "work".  It's roughly
        /// equivalent to the contents of your Script Task code.
        /// </summary>
        public override DTSExecResult Execute(Connections connections, VariableDispenser variableDispenser, IDTSComponentEvents componentEvents, IDTSLogging log, object transaction)
        {
            // Assume failure
            DTSExecResult result = DTSExecResult.Failure;

            // retrieve file name from SSIS variable
            string resolvedFilePathName = "";
            try
            {
                resolvedFilePathName = this.GetResolvedFilePathName(variableDispenser);

                Variable varFileExistence = null;
                Variable varFileLength = null;
                Variable varParsedFileDirectory = null;
                Variable varParsedFileName = null;
                Variable varConstructedFullFilePath = null;
                Variable varFileReadable = null;
                Variable varFileWriteable = null;
                Variable varCreationDate = null;
                Variable varAccessDate = null;
                Variable varModifiedDate = null;
                Variable varArchiveAttribute = null;
                Variable varCompressedAttribute = null;
                Variable varEncryptedAttribute = null;
                Variable varHiddenAttribute = null;
                Variable varReadOnlyAttribute = null;
                Variable varSystemAttribute = null;
                Variable varTemporaryAttribute = null;
                #region Retrieve (and lock) references to the above variables (if they exist)
                Variables vars = null;
                try
                {
                    if (this._varNameFileExistence != null)
                    {
                        variableDispenser.LockForWrite(this._varNameFileExistence);
                    }
                    if (this._varNameFileLength != null)
                    {
                        variableDispenser.LockForWrite(this._varNameFileLength);
                    }
                    if (this._varNameParsedFileDirectory != null)
                    {
                        variableDispenser.LockForWrite(this._varNameParsedFileDirectory);
                    }
                    if (this._varNameParsedFileName != null)
                    {
                        variableDispenser.LockForWrite(this._varNameParsedFileName);
                    }
                    if (this._varNameConstructedFullFilePath!= null)
                    {
                        variableDispenser.LockForWrite(this._varNameConstructedFullFilePath);
                    }
                    if (this._varNameFileReadable != null)
                    {
                        variableDispenser.LockForWrite(this._varNameFileReadable);
                    }
                    if (this._varNameFileWriteable != null)
                    {
                        variableDispenser.LockForWrite(this._varNameFileWriteable);
                    }
                    #region Creation Date
                    if ((this._varNameCreationDate != null) && (this._propertyActionCreationDate != PropertyActionType.Ignore))
                    {
                        if (this._propertyActionCreationDate != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameCreationDate);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameCreationDate);
                        }
                    }
                    #endregion
                    #region Access Date
                    if ((this._varNameAccessDate != null) && (this._propertyActionAccessDate != PropertyActionType.Ignore))
                    {
                        if (this._propertyActionAccessDate != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAccessDate);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAccessDate);
                        }
                    }
                    #endregion
                    #region Modified Date
                    if ((this._varNameModifiedDate != null) && (this._propertyActionModifiedDate != PropertyActionType.Ignore))
                    {
                        if (this._propertyActionModifiedDate != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameModifiedDate);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameModifiedDate);
                        }
                    }
                    #endregion
                    #region Archive Attribute
                    if ((this._varNameAttributeArchive != null) && (this._varNameAttributeArchive != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeArchive != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeArchive != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeArchive);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeArchive);
                        }
                    }
                    #endregion
                    #region Compressed Attribute
                    if ((this._varNameAttributeCompressed != null) && (this._varNameAttributeCompressed != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeCompressed != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeCompressed != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeCompressed);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeCompressed);
                        }
                    }
                    #endregion
                    #region Encrypted Attribute
                    if ((this._varNameAttributeEncrypted != null) && (this._varNameAttributeEncrypted != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeEncrypted != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeEncrypted != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeEncrypted);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeEncrypted);
                        }
                    }
                    #endregion
                    #region Hidden Attribute
                    if ((this._varNameAttributeHidden != null) && (this._varNameAttributeHidden != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeHidden != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeHidden != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeHidden);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeHidden);
                        }
                    }
                    #endregion
                    #region ReadOnly Attribute
                    if ((this._varNameAttributeReadOnly != null) && (this._varNameAttributeReadOnly != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeReadOnly != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeReadOnly != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeReadOnly);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeReadOnly);
                        }
                    }
                    #endregion
                    #region System Attribute
                    if ((this._varNameAttributeSystem != null) && (this._varNameAttributeSystem != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeSystem != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeSystem != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeSystem);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeSystem);
                        }
                    }
                    #endregion
                    #region Temporary Attribute
                    if ((this._varNameAttributeTemporary != null) && (this._varNameAttributeTemporary != VARIABLE_ALWAYSTRUE) && (this._varNameAttributeTemporary != VARIABLE_ALWAYSFALSE))
                    {
                        if (this._propertyActionAttributeTemporary != PropertyActionType.Write)
                        {
                            variableDispenser.LockForWrite(this._varNameAttributeTemporary);
                        }
                        else
                        {
                            variableDispenser.LockForRead(this._varNameAttributeTemporary);
                        }
                    }
                    #endregion

                    variableDispenser.GetVariables(ref vars);

                    #region Attach SSIS Variables to Named Local Variables
                    foreach (Variable lockedVariable in vars)
                    {
                        if (lockedVariable.QualifiedName == this._varNameFileExistence)
                        {
                            varFileExistence = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameFileLength)
                        {
                            varFileLength = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameParsedFileDirectory)
                        {
                            varParsedFileDirectory = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameParsedFileName)
                        {
                            varParsedFileName = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameConstructedFullFilePath)
                        {
                            varConstructedFullFilePath = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameFileReadable)
                        {
                            varFileReadable = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameFileWriteable)
                        {
                            varFileWriteable = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameCreationDate)
                        {
                            varCreationDate = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAccessDate)
                        {
                            varAccessDate = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameModifiedDate)
                        {
                            varModifiedDate = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeArchive)
                        {
                            varArchiveAttribute = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeCompressed)
                        {
                            varCompressedAttribute = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeEncrypted)
                        {
                            varEncryptedAttribute = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeHidden)
                        {
                            varHiddenAttribute = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeReadOnly)
                        {
                            varReadOnlyAttribute = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeSystem)
                        {
                            varSystemAttribute = lockedVariable;
                        }
                        else if (lockedVariable.QualifiedName == this._varNameAttributeTemporary)
                        {
                            varTemporaryAttribute = lockedVariable;
                        }
                    }
                    #endregion
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "File Properties Task",
                        "Unable to retrieve variable information: "
                        + ex.Message, "", 0);
                }
                #endregion
                #endregion

                System.IO.FileInfo fileInfo = null;
                bool fireAgain = true;
                try
                {
                    #region Wait until file exists, if so instructed
                    if (this._fileWaitSeconds > 0)
                    {
                        int quarterSecondsWaited = 0;
                        while (!System.IO.File.Exists(resolvedFilePathName))
                        {
                            System.Threading.Thread.Sleep(250);
                            quarterSecondsWaited++;

                            if ((quarterSecondsWaited / 4) >= this._fileWaitSeconds)
                            {
                                break;
                            }
                        }

                        if (quarterSecondsWaited > 0)
                        {
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Waited " + (quarterSecondsWaited / 4.0).ToString() + "s for file to appear.", "", 0, ref fireAgain);
                        }
                    }
                    #endregion
                    if (!System.IO.File.Exists(resolvedFilePathName))
                    {
                        #region Report the file is missing
                        if ((this._fileMissingAction == FileMissingActionType.Task_Always_Succeeds_and_Records_File_Existence_In_Variable) && (varFileExistence != null))
                        {
                            varFileExistence.Value = false;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "File '" + resolvedFilePathName + "' does NOT exist, recording information in " + varFileExistence.Name + ".", "", 0, ref fireAgain);
                            result = DTSExecResult.Success;
                        }
                        else
                        {
                            componentEvents.FireError(0, "File Properties Task",
                                "File '" + resolvedFilePathName + "' does NOT exist.  Task is configured to fail if the file is missing.", "", 0);
                            result = DTSExecResult.Failure;
                        }
                        #endregion
                    }
                    else
                    {
                        #region Report the file exists
                        if (varFileExistence != null)
                        {
                            varFileExistence.Value = true;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "File '" + resolvedFilePathName + "' exists, recording information in " + varFileExistence.Name + ".", "", 0, ref fireAgain);
                        }
                        else
                        {
                            componentEvents.FireInformation(0, "File Properties Task",
                                "File '" + resolvedFilePathName + "' exists.", "", 0, ref fireAgain);
                        }
                        #endregion

                        #region Attempt to Open the File for Read, Recording Result
                        if (varFileReadable != null)
                        {
                            try
                            {
                                System.IO.FileStream readStream = System.IO.File.OpenRead(resolvedFilePathName);
                                varFileReadable.Value = true;
                                readStream.Close();
                                componentEvents.FireInformation(0, "File Properties Task",
                                    "File '" + resolvedFilePathName + "' is readable, recording information in " + varFileReadable.Name + ".", "", 0, ref fireAgain);
                            }
                            catch
                            {
                                varFileReadable.Value = false;
                                componentEvents.FireInformation(0, "File Properties Task",
                                    "File '" + resolvedFilePathName + "' is NOT readable, recording information in " + varFileReadable.Name + ".", "", 0, ref fireAgain);
                            }
                        }
                        #endregion

                        #region Attempt to Open the File for Write, Recording Result
                        if (varFileWriteable != null)
                        {
                            try
                            {
                                System.IO.FileStream writeStream = System.IO.File.OpenWrite(resolvedFilePathName);
                                varFileWriteable.Value = true;
                                writeStream.Close();
                                componentEvents.FireInformation(0, "File Properties Task",
                                    "File '" + resolvedFilePathName + "' is writable, recording information in " + varFileWriteable.Name + ".", "", 0, ref fireAgain);
                            }
                            catch
                            {
                                varFileWriteable.Value = false;
                                componentEvents.FireInformation(0, "File Properties Task",
                                    "File '" + resolvedFilePathName + "' is NOT writable, recording information in " + varFileWriteable.Name + ".", "", 0, ref fireAgain);
                            }
                        }
                        #endregion

                        #region Write/Read the File's Properties
                        // get FileInfo object that contains file properties
                        fileInfo = new System.IO.FileInfo(resolvedFilePathName);

                        #region Write Properties and Attributes
                        #region Write Creation Date
                        if ((varCreationDate != null)
                            && ((this._propertyActionCreationDate == PropertyActionType.Write) || (this._propertyActionCreationDate == PropertyActionType.Write_Then_Read)))
                        {
                            fileInfo.CreationTime = (DateTime)varCreationDate.Value;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Writing " + varCreationDate.Value.ToString() + " into '" + resolvedFilePathName + "' file creation date.", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Write Access Date
                        if ((varAccessDate != null)
                            && ((this._propertyActionAccessDate == PropertyActionType.Write) || (this._propertyActionAccessDate == PropertyActionType.Write_Then_Read)))
                        {
                            fileInfo.LastAccessTime = (DateTime)varAccessDate.Value;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Writing " + varAccessDate.Value.ToString() + " into '" + resolvedFilePathName + "' file access date.", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Write Modified Date
                        if ((varModifiedDate != null)
                            && ((this._propertyActionModifiedDate == PropertyActionType.Write) || (this._propertyActionModifiedDate == PropertyActionType.Write_Then_Read)))
                        {
                            fileInfo.LastWriteTime = (DateTime)varModifiedDate.Value;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Writing " + varModifiedDate.Value.ToString() + " into '" + resolvedFilePathName + "' file modified date.", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Write Archive Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.Archive, this._propertyActionAttributeArchive, this._varNameAttributeArchive, varArchiveAttribute, 
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #region Write Compressed Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.Compressed, this._propertyActionAttributeCompressed, this._varNameAttributeCompressed, varCompressedAttribute,
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #region Write Encrypted Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.Encrypted, this._propertyActionAttributeEncrypted, this._varNameAttributeEncrypted, varEncryptedAttribute,
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #region Write Hidden Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.Hidden, this._propertyActionAttributeHidden, this._varNameAttributeHidden, varHiddenAttribute,
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #region Write ReadOnly Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.ReadOnly, this._propertyActionAttributeReadOnly, this._varNameAttributeReadOnly, varReadOnlyAttribute,
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #region Write System Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.System, this._propertyActionAttributeSystem, this._varNameAttributeSystem, varSystemAttribute,
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #region Write Temporary Attribute
                        this.Execute_WriteAttribute(System.IO.FileAttributes.Temporary, this._propertyActionAttributeTemporary, this._varNameAttributeTemporary, varTemporaryAttribute,
                            resolvedFilePathName, fileInfo, componentEvents);
                        #endregion
                        #endregion

                        fileInfo.Refresh();

                        #region Read Properties and Attributes
                        #region Parse Directory Name
                        if (varParsedFileDirectory != null)
                        {
                            varParsedFileDirectory.Value = System.IO.Path.GetDirectoryName(resolvedFilePathName);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Parsed '" + resolvedFilePathName + "' file directory of " + varParsedFileDirectory.Value + " into " + varParsedFileDirectory.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Parse File Name
                        if (varParsedFileName != null)
                        {
                            varParsedFileName.Value = System.IO.Path.GetFileName(resolvedFilePathName);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Parsed '" + resolvedFilePathName + "' file name of " + varParsedFileName.Value + " into " + varParsedFileName.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Construct Full File Path
                        if (varConstructedFullFilePath != null)
                        {
                            varConstructedFullFilePath.Value = System.IO.Path.GetFullPath(resolvedFilePathName);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Constructed '" + resolvedFilePathName + "' full file path of " + varConstructedFullFilePath.Value + " into " + varConstructedFullFilePath.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion

                        #region Read File Length
                        if (varFileLength != null)
                        {
                            varFileLength.Value = fileInfo.Length;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' file length of " + varFileLength.Value.ToString() + " into " + varFileLength.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Creation Date
                        if ((varCreationDate != null)
                            && ((this._propertyActionCreationDate == PropertyActionType.Read) || (this._propertyActionCreationDate == PropertyActionType.Write_Then_Read)))
                        {
                            varCreationDate.Value = fileInfo.CreationTime;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' creation date of " + varCreationDate.Value.ToString() + " into " + varCreationDate.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Access Date
                        if ((varAccessDate != null)
                            && ((this._propertyActionAccessDate == PropertyActionType.Read) || (this._propertyActionAccessDate == PropertyActionType.Write_Then_Read)))
                        {
                            varAccessDate.Value = fileInfo.LastAccessTime;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' access date of " + varAccessDate.Value.ToString() + " into " + varAccessDate.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Modified Date
                        if ((varModifiedDate != null)
                            && ((this._propertyActionModifiedDate == PropertyActionType.Read) || (this._propertyActionModifiedDate == PropertyActionType.Write_Then_Read)))
                        {
                            varModifiedDate.Value = fileInfo.LastWriteTime;
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' modified date of " + varModifiedDate.Value.ToString() + " into " + varModifiedDate.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Archive Attribute
                        if ((varArchiveAttribute != null)
                            && ((this._propertyActionAttributeArchive == PropertyActionType.Read) || (this._propertyActionAttributeArchive == PropertyActionType.Write_Then_Read)))
                        {
                            varArchiveAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.Archive) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' archive attribute " + varArchiveAttribute.Value.ToString() + " into " + varArchiveAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Compressed Attribute
                        if ((varCompressedAttribute != null)
                            && ((this._propertyActionAttributeCompressed == PropertyActionType.Read) || (this._propertyActionAttributeCompressed == PropertyActionType.Write_Then_Read)))
                        {
                            varCompressedAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.Compressed) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' compressed attribute " + varCompressedAttribute.Value.ToString() + " into " + varCompressedAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Encrypted Attribute
                        if ((varEncryptedAttribute != null)
                            && ((this._propertyActionAttributeEncrypted == PropertyActionType.Read) || (this._propertyActionAttributeEncrypted == PropertyActionType.Write_Then_Read)))
                        {
                            varEncryptedAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.Encrypted) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' encrypted attribute " + varEncryptedAttribute.Value.ToString() + " into " + varEncryptedAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Hidden Attribute
                        if ((varHiddenAttribute != null)
                            && ((this._propertyActionAttributeHidden == PropertyActionType.Read) || (this._propertyActionAttributeHidden == PropertyActionType.Write_Then_Read)))
                        {
                            varHiddenAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.Hidden) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' hidden attribute " + varHiddenAttribute.Value.ToString() + " into " + varHiddenAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read ReadOnly Attribute
                        if ((varReadOnlyAttribute != null)
                            && ((this._propertyActionAttributeReadOnly == PropertyActionType.Read) || (this._propertyActionAttributeReadOnly == PropertyActionType.Write_Then_Read)))
                        {
                            varReadOnlyAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.ReadOnly) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' readonly attribute " + varReadOnlyAttribute.Value.ToString() + " into " + varReadOnlyAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read System Attribute
                        if ((varSystemAttribute != null)
                            && ((this._propertyActionAttributeSystem == PropertyActionType.Read) || (this._propertyActionAttributeSystem == PropertyActionType.Write_Then_Read)))
                        {
                            varSystemAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.System) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' system attribute " + varSystemAttribute.Value.ToString() + " into " + varSystemAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #region Read Temporary Attribute
                        if ((varTemporaryAttribute != null)
                            && ((this._propertyActionAttributeTemporary == PropertyActionType.Read) || (this._propertyActionAttributeTemporary == PropertyActionType.Write_Then_Read)))
                        {
                            varTemporaryAttribute.Value = ((fileInfo.Attributes & System.IO.FileAttributes.Temporary) > 0);
                            componentEvents.FireInformation(0, "File Properties Task",
                                "Read '" + resolvedFilePathName + "' temporary attribute " + varTemporaryAttribute.Value.ToString() + " into " + varTemporaryAttribute.Name + ".", "", 0, ref fireAgain);
                        }
                        #endregion
                        #endregion

                        // report success!
                        result = DTSExecResult.Success;
                        #endregion
                    }
                }
                #region catch ...
                catch (Exception ex)
                {
                    fileInfo = null;
                    componentEvents.FireError(0, "File Properties Task",
                        "Unable to retrieve information for file '" + resolvedFilePathName + "': "
                        + ex.Message, "", 0);
                }
                #endregion

                #region Release the SSIS variables
                try
                {
                    vars.Unlock();
                }
                #region catch ...
                catch (Exception ex)
                {
                    componentEvents.FireError(0, "File Properties Task",
                        "Unable to release variables: "
                        + ex.Message, "", 0);
                }
                #endregion
                #endregion
            }
            #region catch ...
            catch (Exception ex)
            {
                componentEvents.FireError(0, "File Properties Task",
                    "Unable to determine file name to get properties of: "
                    + ex.Message, "", 0);
            }
            #endregion

            return result;
        }

        private void Execute_WriteAttribute(System.IO.FileAttributes attribute, PropertyActionType propertyAction, string variableName, Variable propertyVariable,
            string resolvedFilePathName, System.IO.FileInfo fileInfo, IDTSComponentEvents componentEvents)
        {
            bool fireAgain = true;
            bool? writeAction = null;
            if ((propertyAction == PropertyActionType.Write) || (propertyAction == PropertyActionType.Write_Then_Read))
            {
                if (propertyVariable != null)
                {
                    writeAction = (bool)propertyVariable.Value;
                }
                else if (variableName == VARIABLE_ALWAYSTRUE)
                {
                    writeAction = true;
                }
                else if (variableName == VARIABLE_ALWAYSFALSE)
                {
                    writeAction = false;
                }
            }
            if (writeAction.HasValue)
            {
                if (writeAction.Value)
                {
                    fileInfo.Attributes = fileInfo.Attributes | attribute;
                }
                else
                {
                    fileInfo.Attributes = fileInfo.Attributes & (~attribute);
                }
                componentEvents.FireInformation(0, "File Properties Task",
                    "Changed '" + resolvedFilePathName + "' " + attribute.ToString() + " attribute to " + writeAction.Value.ToString() + ".", "", 0, ref fireAgain);
            }
        }
        #endregion
        #endregion
    }
}
